package com.easy.user.util;
 
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
 
import javax.net.ssl.SSLContext;
 
import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
import org.apache.hc.client5.http.async.methods.SimpleHttpRequests;
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
import org.apache.hc.core5.concurrent.FutureCallback;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.InputStreamEntity;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import org.apache.hc.core5.net.URIBuilder;
import org.apache.hc.core5.ssl.SSLContexts;
import org.apache.hc.core5.ssl.TrustStrategy;
import org.apache.hc.core5.util.Timeout;

public class HttpUtil {
	
	
	public static CloseableHttpClient httpClient = HttpClients.createDefault();
	static {
		// 设置超时时间
		RequestConfig config = RequestConfig.custom().setConnectTimeout(Timeout.ofMilliseconds(60000L))
				.setConnectionRequestTimeout(Timeout.ofMilliseconds(60000L))
				.setResponseTimeout(Timeout.ofMilliseconds(60000L)).build();
		// 未设置支持ssl
//		httpClient = HttpClients.custom().setDefaultRequestConfig(config).build();
		// httpclient5经测试不设置支持ssl，也能调用https接口
		try {
			httpClient = HttpClients.custom().setDefaultRequestConfig(config)
					.setConnectionManager(getHttpClientConnectionManager()).build();
		} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
			httpClient = HttpClients.createDefault();
			e.printStackTrace();
		}
 
	}
 
	private static HttpClientConnectionManager getHttpClientConnectionManager()
			throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
		// 设置连接池最大连接数1000,最大并发数200，及支持ssl,tls
		return PoolingHttpClientConnectionManagerBuilder.create().setMaxConnTotal(1000).setMaxConnPerRoute(200)
				.setSSLSocketFactory(getSslConnectionSocketFactory()).build();
	}
 
	/**
	 * 支持SSL
	 *
	 * @return SSLConnectionSocketFactory
	 */
	private static SSLConnectionSocketFactory getSslConnectionSocketFactory()
			throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
		TrustStrategy acceptingTrustStrategy = (x509Certificates, s) -> true;
		SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
		return new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());
		//链接tls版本协议，不指定也可以
//		return new SSLConnectionSocketFactory(sslContext,  new String[] {"TLSv1.1","TLSv1.2","TLSv1.3"},
//				  null, new NoopHostnameVerifier());
 
	}
 
	/**
	 * get方式请求
	 * 
	 * @param url
	 * @return
	 */
	public static String get(String url) {
		return get(url, null, null);
	}
 
	/**
	 * 
	 * @param url
	 * @param params
	 * @return
	 */
	public static String get(String url, Map<String, Object> headers, Map<String, Object> params) {
 
		String resultContent = null;
		HttpGet httpGet = new HttpGet(url);
 
		// 设置header
		if (headers != null) {
			for (Map.Entry<String, Object> entry : params.entrySet()) {
				httpGet.addHeader(entry.getKey(), entry.getValue());
			}
		}
		if (params != null && params.size() > 0) {
			// 表单参数
			List<NameValuePair> nvps = new ArrayList<>();
			// GET 请求参数，如果中文出现乱码需要加上URLEncoder.encode
			for (Map.Entry<String, Object> entry : params.entrySet()) {
				nvps.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
			}
			// 增加到请求 URL 中
			try {
				URI uri = new URIBuilder(new URI(url)).addParameters(nvps).build();
				httpGet.setUri(uri);
			} catch (URISyntaxException e) {
				throw new RuntimeException(e);
			}
 
		}
 
		try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
			// 获取状态码
			System.out.println(response.getVersion()); // HTTP/1.1
			System.out.println(response.getCode()); // 200
			System.out.println(response.getReasonPhrase()); // OK
			HttpEntity entity = response.getEntity();
			// 获取响应信息
			resultContent = EntityUtils.toString(entity,"UTF-8");
			// 确保流被完全消费
			EntityUtils.consume(entity);
		} catch (Exception e) {
			e.printStackTrace();
 
		}
 
		return resultContent;
	}
 
	/**
	 * post form请求
	 * 
	 * @param url
	 * @param params
	 * @return
	 */
	public static String postForm(String url, Map<String, String> headers, Map<String, Object> params) {
 
		String result = null;
		HttpPost httpPost = new HttpPost(url);
		// 设置header
		if (headers != null) {
			for (Map.Entry<String, Object> entry : params.entrySet()) {
				httpPost.addHeader(entry.getKey(), String.valueOf(entry.getValue()));
			}
		}
		httpPost.addHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
		// 表单参数
		List<NameValuePair> nvps = new ArrayList<>();
		for (Map.Entry<String, Object> entry : params.entrySet()) {
			nvps.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
		}
//注意编码为UTF-8,否则中文会出现乱码
		httpPost.setEntity(new UrlEncodedFormEntity(nvps,Charset.forName("UTF-8")));
 
		try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
			System.out.println(response.getVersion()); // HTTP/1.1
			System.out.println(response.getCode()); // 200
			System.out.println(response.getReasonPhrase()); // OK
 
			HttpEntity entity = response.getEntity();
			// 获取响应信息
			result = EntityUtils.toString(entity,"UTF-8");
 
			// 确保流被完全消费
			EntityUtils.consume(entity);
		} catch (Exception e) {
			e.printStackTrace();
 
		}
 
		return result;
	}
 
	/**
	 * post form请求,返回Response，有些请求需要拿到header
	 * 
	 * @param url
	 * @param params
	 * @return
	 */
	public static CloseableHttpResponse postFormReturnResponse(String url, Map<String, Object> headers,
			Map<String, Object> params) {
		CloseableHttpResponse response = null;
		HttpPost httpPost = new HttpPost(url);
		httpPost.addHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
 
		// 设置header
		if (headers != null) {
			for (Map.Entry<String, Object> entry : params.entrySet()) {
				httpPost.addHeader(entry.getKey(), entry.getValue());
			}
		}
		// 表单参数
		List<NameValuePair> nvps = new ArrayList<>();
		// POST 请求参数
		for (Map.Entry<String, Object> entry : params.entrySet()) {
			nvps.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
		}
		httpPost.setEntity(new UrlEncodedFormEntity(nvps,Charset.forName("UTF-8")));
 
		try {
			response = httpClient.execute(httpPost);
//			Header[] header=response.getHeaders();
			System.out.println(response.getVersion()); // HTTP/1.1
			System.out.println(response.getCode()); // 200
			System.out.println(response.getReasonPhrase()); // OK
//
//			HttpEntity entity = response.getEntity();
//			// 获取响应信息
//			result = EntityUtils.toString(entity);
//			// 确保流被完全消费
//			EntityUtils.consume(entity);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return response;
	}
 
	/**
	 * post json请求
	 * 
	 * @param url
	 * @param jsonBody
	 * @return
	 */
	public static String postJson(String url, String jsonBody) {
 
		String result = null;
		HttpPost httpPost = new HttpPost(url);
		httpPost.addHeader("Content-Type","application/json;charset=UTF-8");
		httpPost.setEntity(new StringEntity(jsonBody, ContentType.APPLICATION_JSON));
 
		try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
			// 获取响应信息
			result = EntityUtils.toString(response.getEntity(),"UTF-8");
		} catch (IOException | ParseException e) {
			e.printStackTrace();
 
		}
 
		return result;
	}
 
	/**
	 * post stream请求(file,json,xml转stream)
	 * 
	 * @param url
	 * @param jsonBody
	 * @return
	 */
	public static String postStream(String url, String params, ContentType contentType) {
		String result = null;
		final HttpPost httppost = new HttpPost(url);
		InputStream inputStream = new ByteArrayInputStream(new String(params).getBytes());
		final InputStreamEntity reqEntity = new InputStreamEntity(inputStream, -1, contentType);
		// 也可以使用 FileEntity 的形式
		// FileEntity reqEntity = new FileEntity(new File(params),
		// ContentType.APPLICATION_JSON);
 
		httppost.setEntity(reqEntity);
		try (final CloseableHttpResponse response = httpClient.execute(httppost)) {
			System.out.println("----------------------------------------");
			System.out.println(response.getCode() + " " + response.getReasonPhrase());
			result = EntityUtils.toString(response.getEntity(),"UTF-8");
			System.out.println(result);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
 
	/**
	 * getAsync异步请求，回调获取结果
	 *
	 * @param url
	 * @return
	 */
	public static String getAsync(String url) {
		try (CloseableHttpAsyncClient httpclient = HttpAsyncClients.createDefault()) {
			// 开始 http clinet
			httpclient.start();
			// 根据请求响应情况进行回调操作
//            CountDownLatch latch = new CountDownLatch(1);
			SimpleHttpRequest request = SimpleHttpRequests.get(url);
			httpclient.execute(request, new FutureCallback<SimpleHttpResponse>() {
				@Override
				public void completed(SimpleHttpResponse response2) {
//                    latch.countDown();
					System.out.println("getAsync:" + request.getRequestUri() + "->" + response2.getCode());
				}
 
				@Override
				public void failed(Exception ex) {
//                    latch.countDown();
					System.out.println("getAsync:" + request.getRequestUri() + "->" + ex);
				}
 
				@Override
				public void cancelled() {
//                    latch.countDown();
					System.out.println("getAsync:" + request.getRequestUri() + " cancelled");
				}
 
			});
//            latch.await();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return null;
	}
 
//	public static void main(String[] args) {
//		String newPayUrl="https://restapi.amap.com/v3/config/district?key=d5e466c74f37e2b1f89163a68a161ea7&keywords=100000";
//		String response=get(newPayUrl);
//		System.out.println(response);
// 
//	}
 
}